﻿using System.Runtime.InteropServices;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Resources;
using System.IO;
using System.Security;
using System.Text;
using System.Media;
using System.Threading;

namespace 语音朗读机器人
{
    public class TTSAPIClass
    {
        private static string path = AppDomain.CurrentDomain.BaseDirectory + @"Addons\ttsc\";
        private string pzConfig = "authPath=" + path + ",cloudUrl=test.api.hcicloud.com:8888,developerKey=a9f6f58b60c124b5c5217153ea4927f5,appKey=cd5d5440,logFilePath=" + path + ",logLevel=5,logFileSize=3,logFileCount=9";
        public delegate void SendMSG(string msg, bool action = false);
        public event SendMSG SMSG;
        public bool IsInit = false;
        private int NowSessionID = 0;
        private string nowfile;
        public string NowSpeaker = "tts.cloud.wangjing";
        public bool CanSpeak = true;
        public void Init()
        {
            HCI_ERR_CODE initres = (HCI_ERR_CODE)hci_init(pzConfig);
            if (initres == HCI_ERR_CODE.HCI_ERR_NONE)
            {
                HCI_ERR_CODE res = (HCI_ERR_CODE)hci_tts_init(string.Format("dataPath={0},initCapKeys={1}", path, "tts.cloud.xixi;tts.cloud.donna;tts.cloud.xiaokun;"));
                if (res == HCI_ERR_CODE.HCI_ERR_NONE)
                {
                    SMSG("二号语音引擎启动完毕，准备发射");
                    IsInit = true;
                }
            }
            else
            {
                IsInit = false;
            }

        }
        public int SessionStart(string capKey)
        {
            int sessionid = 0;
            string pszConfig = "audioFormat=mp3,speedUp=2,encLevel=0";
            HCI_ERR_CODE res = (HCI_ERR_CODE)hci_tts_session_start("capKey=" + capKey + "," + pszConfig, out sessionid);
            if (res == HCI_ERR_CODE.HCI_ERR_NONE)
            {
                NowSessionID = sessionid;
                return sessionid;
            }
            else
            {
                return -1;
            }
        }
        public bool SessionStop(int sessionid)
        {
            if ((HCI_ERR_CODE)hci_tts_session_stop(sessionid) == HCI_ERR_CODE.HCI_ERR_NONE)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void Shutdown()
        {
            SessionStop(NowSessionID);
            try
            {
                foreach (string d in Directory.GetFileSystemEntries(path))
                {
                    if (File.Exists(d))
                    {
                        FileInfo fi = new FileInfo(d);
                        if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1)
                            fi.Attributes = FileAttributes.Normal;
                        File.Delete(d);//直接删除其中的文件  
                    }
                    else
                    {
                        DirectoryInfo d1 = new DirectoryInfo(d);
                        Directory.Delete(d);
                    }
                }
            }
            catch (Exception)
            {
            }
        }
        public void tts_synth(string txt)
        {
            IntPtr fip = IntPtr.Zero;
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            nowfile = path + Convert.ToInt64(ts.TotalSeconds).ToString() + "out.mp3";
            try
            {
                //必须转换编码，灵云只接受UTF8的编码
                byte[] ccc = Encoding.Default.GetBytes(txt);
                ccc = Encoding.Convert(Encoding.GetEncoding("gb2312"), Encoding.UTF8, ccc);
                string utf8s = Encoding.Default.GetString(ccc);
                hci_tts_synth(NowSessionID, utf8s, null, new Callback_TtsSynth(callback), IntPtr.Zero);
            }
            catch (Exception)
            {
                SMSG("提取文本出错了");
            }
        }
        public void tts_setvol(double vol)
        {

        }
        public void tts_setspeed(double vol)
        {

        }
        public void ChangeSpeaker(string capKey)
        {
            if (NowSessionID != 0)
            {
                SessionStop(NowSessionID);
                NowSpeaker = capKey;
                SessionStart(NowSpeaker);
            }
        }
        bool callback(IntPtr pvUserParam, IntPtr psTtsSynthResult, int hciErrCode)
        {
            if ((HCI_ERR_CODE)hciErrCode != HCI_ERR_CODE.HCI_ERR_NONE)
            {
                return false;
            }

            // 这里的pvUserParam 就是 hci_tts_synth()时传入的最后一个参数
            try
            {
                TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                nowfile = path + Convert.ToInt64(ts.TotalSeconds).ToString() + "out.mp3";
                using (FileStream fs = System.IO.File.Create(nowfile))
                {
                    TTS_SYNTH_RESULT _psTtsSynthResult = new TTS_SYNTH_RESULT();
                    _psTtsSynthResult = (TTS_SYNTH_RESULT)Marshal.PtrToStructure(psTtsSynthResult, typeof(TTS_SYNTH_RESULT));
                    if (_psTtsSynthResult.pvVoiceData != null && _psTtsSynthResult.uiVoiceSize != 0)
                    {
                        byte[] data = new byte[(int)_psTtsSynthResult.uiVoiceSize];
                        Marshal.Copy(_psTtsSynthResult.pvVoiceData, data, 0, (int)_psTtsSynthResult.uiVoiceSize);
                        // 将合成结果写入文件
                        fs.Write(data, 0, (int)_psTtsSynthResult.uiVoiceSize);
                        fs.Flush();
                        fs.Close();
                        Thread.Sleep(100);
                        SMSG("蒙蔽机器人的心脏.playsound:" + nowfile, true);
                    }
                }
            }
            catch (Exception)
            {
                SMSG("输出语音朗读文件失败");
            }
            // 此回调函数返回false会中止合成，返回true表示继续合成
            return true;
        }

        enum HCI_ERR_CODE
        {
            HCI_ERR_UNKNOWN = -1, HCI_ERR_NONE = 0, HCI_ERR_PARAM_INVALID, HCI_ERR_OUT_OF_MEMORY,
            HCI_ERR_CONFIG_INVALID, HCI_ERR_CONFIG_CAPKEY_MISSING, HCI_ERR_CONFIG_CAPKEY_NOT_MATCH, HCI_ERR_CONFIG_DATAPATH_MISSING,
            HCI_ERR_CONFIG_UNSUPPORT, HCI_ERR_SERVICE_CONNECT_FAILED, HCI_ERR_SERVICE_TIMEOUT, HCI_ERR_SERVICE_DATA_INVALID,
            HCI_ERR_SERVICE_RESPONSE_FAILED, HCI_ERR_CAPKEY_NOT_FOUND, HCI_ERR_NOT_LOCAL_CAPKEY, HCI_ERR_LOCAL_LIB_MISSING,
            HCI_ERR_URL_MISSING, HCI_ERR_SESSION_INVALID, HCI_ERR_TOO_MANY_SESSION, HCI_ERR_ACTIVE_SESSION_EXIST,
            HCI_ERR_START_LOG_FAILED, HCI_ERR_DATA_SIZE_TOO_LARGE, HCI_ERR_LOAD_CODEC_DLL, HCI_ERR_UNSUPPORT,
            HCI_ERR_LOAD_FUNCTION_FROM_DLL, HCI_ERR_TXACCOUNT_NOT_FOUND, HCI_ERR_SYS_NOT_INIT = 100, HCI_ERR_SYS_ALREADY_INIT,
            HCI_ERR_SYS_CONFIG_AUTHPATH_MISSING, HCI_ERR_SYS_CONFIG_CLOUDURL_MISSING, HCI_ERR_SYS_CONFIG_USERID_MISSING, HCI_ERR_SYS_CONFIG_PASSWORD_MISSING,
            HCI_ERR_SYS_CONFIG_PLATFORMID_MISSING, HCI_ERR_SYS_CONFIG_DEVELOPERID_MISSING, HCI_ERR_SYS_CONFIG_DEVELOPERKEY_MISSING, HCI_ERR_SYS_CONFIG_APPNO_MISSING,
            HCI_ERR_SYS_USERINFO_INVALID, HCI_ERR_SYS_AUTHFILE_INVALID, HCI_ERR_SYS_CHECKAUTH_RESPONSE_FAILED, HCI_ERR_SYS_REGISTER_RESPONSE_FAILED,
            HCI_ERR_SYS_USING, HCI_ERR_SYS_CONFIG_APPKEY_MISSING, HCI_ERR_ASR_NOT_INIT = 200, HCI_ERR_ASR_ALREADY_INIT,
            HCI_ERR_ASR_CONFIRM_NO_TASK, HCI_ERR_ASR_PARAM_CHECK_FLAG_INVALID, HCI_ERR_ASR_GRAMMAR_DATA_TOO_LARGE, HCI_ERR_ASR_ENGINE_NOT_INIT,
            HCI_ERR_ASR_ENGINE_INIT_FAILED, HCI_ERR_ASR_OPEN_GRAMMAR_FILE, HCI_ERR_ASR_LOAD_GRAMMAR_FAILED, HCI_ERR_ASR_ENGINE_FAILED,
            HCI_ERR_ASR_GRAMMAR_ID_INVALID, HCI_ERR_ASR_REALTIME_WAITING, HCI_ERR_ASR_GRAMMAR_OVERLOAD, HCI_ERR_ASR_GRAMMAR_USING,
            HCI_ERR_ASR_REALTIME_END, HCI_ERR_ASR_UPLOAD_NO_DATA, HCI_ERR_HWR_NOT_INIT = 300, HCI_ERR_HWR_ALREADY_INIT,
            HCI_ERR_HWR_CONFIRM_NO_TASK, HCI_ERR_HWR_ENGINE_INIT_FAILED, HCI_ERR_HWR_ENGINE_FAILED, HCI_ERR_HWR_UPLOAD_NO_DATA,
            HCI_ERR_HWR_ENGINE_SESSION_START_FAILED, HCI_ERR_HWR_ENGINE_NOT_INIT, HCI_ERR_HWR_CONFIG_SUBLANG_MISSING, HCI_ERR_HWR_TOO_MANY_DOMAIN,
            HCI_ERR_OCR_NOT_INIT = 400, HCI_ERR_OCR_ALREADY_INIT, HCI_ERR_OCR_ENGINE_INIT_FAILED, HCI_ERR_OCR_ENGINE_FAILED,
            HCI_ERR_OCR_ENGINE_NOT_INIT, HCI_ERR_OCR_LOAD_IMAGE, HCI_ERR_OCR_SAVE_IMAGE, HCI_ERR_OCR_IMAGE_NOT_SET,
            HCI_ERR_OCR_LOAD_TEMPLATE_FAILED, HCI_ERR_OCR_TEMPLATE_OVERLOAD, HCI_ERR_OCR_TEMPLATE_ID_INVALID, HCI_ERR_OCR_TEMPLATE_USING,
            HCI_ERR_OCR_DETECT_CORNER_FAILED, HCI_ERR_OCR_NORMALIZE_FAILED, HCI_ERR_OCR_RECOGNIZABLE_FAILED, HCI_ERR_OCR_IMAGE_NOT_CLEAR,
            HCI_ERR_TTS_NOT_INIT = 500, HCI_ERR_TTS_ALREADY_INIT, HCI_ERR_TTS_SESSION_BUSY, HCI_ERR_TTS_ENGINE_SESSION_START_FAILED,
            HCI_ERR_TTS_ENGINE_FAILED, HCI_ERR_TTS_ENGINE_INIT_FAILED, HCI_ERR_TTS_ENGINE_NOT_INIT, HCI_ERR_MT_NOT_INIT = 600,
            HCI_ERR_MT_ALREADY_INIT, HCI_ERR_NLU_NOT_INIT = 700, HCI_ERR_NLU_ALREADY_INIT, HCI_ERR_NLU_ENGINE_SESSION_START_FAILED,
            HCI_ERR_NLU_ENGINE_FAILED, HCI_ERR_KB_NOT_INIT = 800, HCI_ERR_KB_ALREADY_INIT, HCI_ERR_KB_ENGINE_SESSION_START_FAILED,
            HCI_ERR_KB_ENGINE_FAILED, HCI_ERR_KB_SYLLABLE_INVALID, HCI_ERR_KB_UDB_WORD_EXIST, HCI_ERR_KB_CONFIRM_NO_TASK,
            HCI_ERR_VPR_NOT_INIT = 900, HCI_ERR_VPR_ALREADY_INIT, HCI_ERR_VPR_ENGINE_INIT_FAILED, HCI_ERR_VPR_ENGINE_FAILED,
            HCI_ERR_VPR_USERID_NOT_EXIST, HCI_ERR_VPR_ENGINE_SESSION_START_FAILED, HCI_ERR_VPR_CONFIG_USER_ID_MISSING, HCI_ERR_FPR_NOT_INIT = 1000,
            HCI_ERR_FPR_ALREADY_INIT, HCI_ERR_FPR_ENGINE_INIT_FAILED, HCI_ERR_FPR_ENGINE_FAILED, HCI_ERR_FPR_USERID_NOT_EXIST,
            HCI_ERR_FPR_ENGINE_SESSION_START_FAILED, HCI_ERR_FPR_CONFIG_USER_ID_MISSING, HCI_ERR_FPR_CONFIG_DPI_MISSING, HCI_ERR_FPR_CONFIG_BGCOLOR_MISSING,
            HCI_ERR_FPR_CONFIG_WIDTH_MISSING, HCI_ERR_FPR_CONFIG_HEIGHT_MISSING
        }
        [DllImport(@"hci_sys.dll")]
        [SuppressUnmanagedCodeSecurity]
        public extern static int hci_init(string config);
        [DllImport(@"hci_tts.dll")]
        [SuppressUnmanagedCodeSecurity]
        public extern static int hci_tts_init(string config);
        [DllImport(@"hci_tts.dll")]
        [SuppressUnmanagedCodeSecurity]
        public extern static int hci_tts_session_start(string config, out int sessionid);
        [DllImport(@"hci_tts.dll")]
        [SuppressUnmanagedCodeSecurity]
        public extern static int hci_tts_session_stop(int sessionid);
        public delegate bool Callback_TtsSynth
        (
            IntPtr pvUserParam,
            IntPtr psTtsSynthResult,
            int hciErrCode
        );
        [DllImport(@"hci_tts.dll", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
        [SuppressUnmanagedCodeSecurity]
        public extern static int hci_tts_synth(int nSessionId, string pvText, string pszConfig, Callback_TtsSynth pfnTtsSynth, IntPtr pvUserParam);
        //播放部分
    }
    struct TTS_SYNTH_RESULT
    {
        public IntPtr pvVoiceData;
        public uint uiVoiceSize;
        public string pszText;
        public uint uiTextLen;
        public bool bMore;
    }
}
